package com.expense.common.util;

import cn.hutool.core.util.StrUtil;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * Created by J on 2017/3/20.
 */
public class UploadFileUtil {

    /**
     * 图片上传
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static Map<String,Object> uploadImage(MultipartFile file, String filePath, List<String> fileSuffix, Long allowFileSize, Boolean isRename) throws IOException {
        if (fileSuffix == null) {
            fileSuffix = new ArrayList<>();
            fileSuffix.add(".png");
            fileSuffix.add(".gif");
            fileSuffix.add(".jpg");
            fileSuffix.add(".jpeg");
        }
        isRename = isRename == null ? true : isRename;
        return toUploadFile(file, filePath, fileSuffix, allowFileSize, isRename, null);
    }
    public static Map<String, Object> uploadFile(MultipartFile file, String filePath, List<String> fileSuffix, Long allowFileSize, Boolean isRename)
            throws IOException {
        if (fileSuffix == null) {
            fileSuffix = new ArrayList<>();
            fileSuffix.add(".txt");
            fileSuffix.add(".doc");
            fileSuffix.add(".docx");
            fileSuffix.add(".xls");
            fileSuffix.add(".xlsx");
        }
        isRename = isRename == null ? true : isRename;
        return toUploadFile(file, filePath, fileSuffix, allowFileSize,isRename, null);
    }
    public static Map<String, Object> uploadFile(MultipartFile file, String filePath, Long allowFileSize, Boolean isRename)
            throws IOException {
        isRename = isRename == null ? true : isRename;
        return toUploadFile(file, filePath, null, allowFileSize,isRename, null);
    }

    protected static Map<String, Object> toUploadFile(MultipartFile file, String filePath, List<String> fileSuffix, Long allowFileSize, Boolean isRename, String extension)
            throws IOException {
        allowFileSize = allowFileSize == null ? 20 * 1024 * 1024 : allowFileSize;
        String allowSize = "";
        if(allowFileSize>(1024*1024)) {
            allowSize = (allowFileSize / 1024 / 1024) + "MB";
        }else {
            allowSize = (allowFileSize / 1024) + "K";
        }
        if (fileSuffix == null) {
            fileSuffix = new ArrayList<>();
            fileSuffix.add(".png");
            fileSuffix.add(".gif");
            fileSuffix.add(".jpg");
            fileSuffix.add(".jpeg");
            fileSuffix.add(".txt");
            fileSuffix.add(".doc");
            fileSuffix.add(".docx");
            fileSuffix.add(".xls");
            fileSuffix.add(".xlsx");
            fileSuffix.add(".ppt");
            fileSuffix.add(".pptx");
        }
        String suffix = file.getOriginalFilename().substring(
                file.getOriginalFilename().lastIndexOf("."));
        long fileSize = file.getSize();
        Map<String, Object> map = new HashMap<String, Object>();
        boolean isAllow = false;
        for (String fs : fileSuffix) {
            if (suffix.equals(fs)) {
                isAllow = true;
                break;
            }
        }
        if (isAllow) {
            if (fileSize < allowFileSize) {
                try {
                    String fileName = file.getOriginalFilename();
                    fileName = new String(fileName.getBytes("ISO-8859-1"), "UTF-8");
                    String fullName = fileName;
                    if(isRename) {
                        fullName = UUID.randomUUID() + (extension == null ? suffix : extension);
                    }
                    File dest = new File(filePath, fullName);

                    if (!dest.getParentFile().exists()) {
                        dest.getParentFile().mkdirs();//如果是多级文件使用mkdirs();如果就一层级的话，可以使用mkdir()
                    }
                    BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
                    out.write(file.getBytes());
                    out.flush();
                    out.close();
//                    if (!dest.exists()) {
//                        dest.createNewFile();
//                    }
//
//                    file.transferTo(dest);

                    map.put("RESULT", "000");
                    map.put("DATA", dest.getName());
                }catch (Exception ex){
                    //ex.printStackTrace();
                    map.put("RESULT","error");
                    map.put("DATA",ex.getMessage());
                }

            } else {
                map.put("RESULT", "error");
                map.put("DATA", "上传文件大小不能超过 " + allowSize);
            }

        } else {
            map.put("RESULT", "error");
            map.put("DATA", "文件格式不正确");
        }
        return map;
    }

    /**
     * 删除文件
     * @param filePath 要删除的文件路径（包含文件名）
     * @return
     * @throws IOException
     * @throws Exception
     */
    public static Map<String, Object> deleteFile(String filePath) throws IOException,Exception {
        Map<String, Object> map = new HashedMap();
        try {
            if (StrUtil.isEmpty(filePath)) {
                throw new Exception("参数不能为空");
            }
            File file = new File(filePath);
            // 判断目录或文件是否存在
            if (!file.exists()) {  // 不存在返回 false
//                throw new IOException("文件不存在");
                map.put("RESULT", "000");
                map.put("DATA", "删除文件成功");
            } else {
                // 判断是否为文件
                if (file.isFile()) {  // 为文件时调用删除文件方法
                    if (file.delete()) {
                        map.put("RESULT", "000");
                        map.put("DATA", "删除文件成功");
                    }
                } else {  // 为目录时 throw 错误
                    throw new IOException("路径：" + filePath + " 不是文件");
                }
            }
        } catch (IOException ex) {
            map.put("RESULT", "error");
            map.put("DATA", ex.getMessage());
        } catch (Exception ex) {
            map.put("RESULT", "error");
            map.put("DATA", ex.getMessage());
        }
        return map;
    }

    /**
     * 删除目录及目录下的文件
     * @param dir 要删除的目录的文件路径
     * @return
     * @throws IOException
     * @throws Exception
     */
    public static Map<String, Object> deleteDirectory(String dir) throws IOException,Exception {
        Map<String, Object> map = new HashedMap();
        try {
            // 如果dir不以文件分隔符结尾，自动添加文件分隔符
            if (!dir.endsWith(File.separator))
                dir = dir + File.separator;
            File dirFile = new File(dir);
            // 如果dir对应的文件不存在，或者不是一个目录，则退出
            if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
                throw new IOException("目录 " + dir + "不存在！");
            }
            // 删除文件夹中的所有文件包括子目录
            boolean flag = true;
            File[] files = dirFile.listFiles();
            for (int i = 0; i < files.length; i++) {
                // 删除子文件
                if (files[i].isFile()) {
                    map = deleteFile(files[i].getAbsolutePath());
                }
                // 删除子目录
                else if (files[i].isDirectory()) {
                    map = deleteDirectory(files[i].getAbsolutePath());
                }
                if (!map.get("RESULT").equals("000")) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                // 删除当前目录
                if (dirFile.delete()) {
                    map.put("RESULT", "000");
                    map.put("DATA", "删除目录成功");
                }
            }
        } catch (IOException ex) {
            map.put("RESULT", "error");
            map.put("DATA", ex.getMessage());
        } catch (Exception ex) {
            map.put("RESULT", "error");
            map.put("DATA", ex.getMessage());
        }
        return map;
    }

}
